home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac-Source 1994 July
/
Mac-Source_July_1994.iso
/
Add-ons
/
VideoShop Plug-In Kit 1.0
/
SampleXsn.c
< prev
next >
Wrap
Text File
|
1992-05-06
|
10KB
|
427 lines
/*
SampleXsn.c
Sample transition effect for VideoShop
*/
/* Includes */
#include <Types.h>
#include <Memory.h>
#include <Resources.h>
#include <QuickDraw.h>
#include <QDOffscreen.h>
#include <Dialogs.h>
#include <OSUtils.h>
#include <Packages.h>
#include <Errors.h>
#include <ToolUtils.h>
#include <SysEqu.h>
#include <Math.h>
#include <GestaltEqu.h>
#include "DiVATransition.h"
/* Type definitions */
typedef struct WipeParams {
unsigned short angle;
} WipeParams, *WipeParamPtr, **WipeParamHandle;
/* Konstants */
#define dialogID 16001
#define defaultItem 3
#define leftToRightItem 5
#define topToBottomItem 6
#define rightToLeftItem 7
#define bottomToTopItem 8
#define dividerItem 10
/* Prototypes */
XsnErr DoParameters (XsitionParamPtr params);
XsnErr DoProcessFrame (XsitionParamPtr params, short transitionIntensity,
short maxTransitionIntensity);
pascal XsnErr XsnEntryPoint (short selector, XsitionParamPtr params, long *data,
short transitionIntensity, short maxTransitionIntensity)
/*
The transition entry point and dispatcher routine. Calls the appropriate
subroutine based on the selector passed.
*/
{
#pragma unused(data)
switch (selector) {
case XSParameters:
return (DoParameters (params));
break;
case XSPrepare:
case XSStart:
case XSFinish:
return (noErr);
break;
case XSProcessFrame:
return (DoProcessFrame (params, transitionIntensity, maxTransitionIntensity));
break;
default:
return (-1);
}
}
pascal Boolean DoTestAbort (ProcPtr codeAddress)
/* Inline code to call the TestAbort function */
= {0x205F, // move.l (a7)+,a0 pop procPtr from stack
0x4E90}; // jsr (a0) and call it
Boolean TestAbort (XsitionParamPtr params)
{
ProcPtr address;
address = params->abortProc;
return (DoTestAbort (address));
}
pascal void DoUpdateProgress (long done, long total, ProcPtr codeAddress)
/* Inline code to call the UpdateProgress function */
= {0x205F, // move.l (a7)+,a0 pop procPtr from stack
0x4E90}; // jsr (a0) and call it
void UpdateProgress (XsitionParamPtr params, long done, long total)
{
ProcPtr address;
address = params->progressProc;
DoUpdateProgress (done, total, address);
}
void CenterDialog (DialogTHndl dt)
/*
Given a dialog template in dt, modify it so as to center the dialog on the
main device.
*/
{
Rect r;
short width;
short height;
GDHandle mainDevice;
mainDevice = GetMainDevice();
width = (**mainDevice).gdRect.right;
height = (**mainDevice).gdRect.bottom;
r = (**dt).boundsRect;
OffsetRect (&r, -r.left, -r.top);
OffsetRect (&r, (width - r.right) / 2,
(height - r.bottom - GetMBarHeight()) / 3 + GetMBarHeight());
(**dt).boundsRect = r;
}
pascal void OutlineOK (DialogPtr dp, short item)
/*
userItem drawing routine for outlining the default button in the dialog box
*/
{
Rect r;
Handle h;
short itemType;
item = ok;
GetDItem (dp, item, &itemType, &h, &r);
PenNormal ();
PenSize (3, 3);
InsetRect (&r, -4, -4);
FrameRoundRect (&r, 16, 16);
PenNormal ();
}
GDHandle GetWindowGDevice(WindowPtr w)
/*
Find the deepest gdevice the window intersects. Used for determining the depth
of the screen we're drawing on (to look good on B/W displays).
*/
{
Rect r=w->portRect;
GrafPtr oldPort;
GDHandle theGD;
GetPort (&oldPort);
SetPort (w);
LocalToGlobal((Point *)&r);
LocalToGlobal((Point *)(&(r.bottom)));
theGD = GetMaxDevice(&r);
SetPort (oldPort);
return (theGD);
}
pascal void DrawLines (DialogPtr theDialog, short itemNo)
/*
userItem drawing routine for dividing lines (with shadow)
*/
{
RGBColor oldColor,greyColor;
short itemType;
Handle me;
Rect box;
GetDItem(theDialog,itemNo,&itemType,&me,&box);
GetForeColor(&oldColor);
RGBForeColor((RGBColor*)RGBBlack);
MoveTo(box.left,box.top);
LineTo(box.right-2,box.top);
MoveTo(box.left,box.top+3);
LineTo(box.right-2,box.top+3);
if (((**((*GetWindowGDevice(theDialog))->gdPMap)).pixelSize >= 8)) {
greyColor.red = greyColor.green = greyColor.blue = 0x7777;
RGBForeColor (&greyColor);
MoveTo(box.left+1,box.top+1);
LineTo(box.right-1,box.top+1);
MoveTo(box.left+1,box.top+4);
LineTo(box.right-1,box.top+4);
}
RGBForeColor(&oldColor);
}
void SetupDItems (DialogPtr dp)
/*
Set up the dialog items
*/
{
Rect r;
short itemType;
Handle item;
// default outline
GetDItem (dp, defaultItem, &itemType, &item , &r);
SetDItem (dp, defaultItem, itemType, (Handle) &OutlineOK, &r);
// dividing lines
GetDItem (dp, dividerItem, &itemType, &item , &r);
SetDItem (dp, dividerItem, itemType, (Handle) DrawLines, &r);
}
/*
Macro to disable all but one dialog items in a given range. Used for managing
sets of radio buttons.
*/
#define DisableAllButMe(i) for (j=leftToRightItem; j<=bottomToTopItem; j++) { \
if (j==i) continue; GetDItem (dp,j,&itemType,&h,&r); \
SetCtlValue((ControlHandle)h,0); }
void RecalcDItems (WipeParamHandle p, DialogPtr dp)
{
short itemType,j;
Handle h;
Rect r;
switch ((**p).angle) {
case 0:
DisableAllButMe(bottomToTopItem);
GetDItem (dp,bottomToTopItem,&itemType,&h,&r);
SetCtlValue ((ControlHandle)h,1);
break;
case 90:
DisableAllButMe(leftToRightItem);
GetDItem (dp,leftToRightItem,&itemType,&h,&r);
SetCtlValue ((ControlHandle)h,1);
break;
case 180:
DisableAllButMe(topToBottomItem);
GetDItem (dp,topToBottomItem,&itemType,&h,&r);
SetCtlValue ((ControlHandle)h,1);
break;
case 270:
DisableAllButMe(rightToLeftItem);
GetDItem (dp,rightToLeftItem,&itemType,&h,&r);
SetCtlValue ((ControlHandle)h,1);
break;
}
}
XsnErr DoParameters (XsitionParamPtr params)
/*
Prompt the user for parameters if necessary.
*/
{
short item;
DialogPtr dp;
DialogTHndl dt;
WipeParamHandle theParams;
/* If we didn't get passed a params handle, allocate and initialize it */
if (!params->parameters) {
params->parameters = NewHandle (sizeof (WipeParams));
if (!params->parameters) return (XSErrOutOfMemory|MemError());
theParams = (WipeParamHandle) params->parameters;
(**theParams).angle = 90;
} else
/*
Otherwise, we just return. If we required specific hardware or mounds of
memory we would check here.
*/
return(noErr);
/* Load in the dialog and center it */
dt = (DialogTHndl) GetResource ('DLOG', dialogID);
HNoPurge ((Handle) dt);
CenterDialog (dt);
/* Show it */
dp = GetNewDialog (dialogID, nil, (WindowPtr) -1);
/* Setup the user items and initialize all controls to initial state */
SetupDItems (dp);
RecalcDItems (theParams, dp);
do {
ModalDialog (nil, &item);
switch (item) {
case topToBottomItem:
(**theParams).angle=180;
RecalcDItems (theParams, dp);
break;
case leftToRightItem:
(**theParams).angle=90;
RecalcDItems (theParams, dp);
break;
case bottomToTopItem:
(**theParams).angle=0;
RecalcDItems (theParams, dp);
break;
case rightToLeftItem:
(**theParams).angle=270;
RecalcDItems (theParams, dp);
break;
}
} while (item != ok && item != cancel);
DisposDialog (dp);
HPurge ((Handle) dt);
if (item == cancel) {
DisposHandle ((Handle)theParams);
params->parameters = nil;
return (XSErrReported);
}
return (noErr);
}
XsnErr DoProcessFrame (XsitionParamPtr params, short transitionIntensity, short maxTransitionIntensity)
/* Perform the effect */
{
PixMapHandle srcA,srcB,dest;
GWorldFlags pmStateA,pmStateB,pmStateDest;
unsigned char stateA,stateB,stateDest;
Rect r,bounds;
GWorldPtr oldGW, destGW;
GDHandle oldGD;
short ySize,xSize;
short angle;
RGBColor oldFore,oldBack;
if (TestAbort (params)) return (XSErrReported);
srcA = params->srcA;
srcB = params->srcB;
destGW = params->destImage;
/* Get the image pixmaps, dealing with pre-System 7 GetGWorldPixMap bug */
if (*((short*)SysVersion)<0x700) {
dest = destGW->portPixMap;
} else {
dest = GetGWorldPixMap (destGW);
}
r = (**srcA).bounds;
ySize = r.bottom - r.top;
xSize = r.right - r.left;
UpdateProgress (params,0,3);
/* Calculate the rectangle to copy based on the wipe direction */
angle = (**((WipeParamHandle)(params->parameters))).angle;
switch (angle) {
case 0:
SetRect (&r,0,0,xSize,ySize);
r.top = r.bottom - (transitionIntensity * xSize / maxTransitionIntensity);
break;
case 90:
SetRect (&r,0,0,xSize,ySize);
r.right = r.left + (transitionIntensity * xSize / maxTransitionIntensity);
break;
case 180:
SetRect (&r,0,0,xSize,ySize);
r.bottom = r.top + (transitionIntensity * ySize / maxTransitionIntensity);
break;
case 270:
SetRect (&r,0,0,xSize,ySize);
r.left = r.right - (transitionIntensity * xSize / maxTransitionIntensity);
break;
}
/* spin the beachball */
UpdateProgress (params,1,3);
/* save offscreen pixels state and lock them down for drawing */
pmStateA = GetPixelsState(srcA);
LockPixels (srcA);
stateA = HGetState ((Handle)srcA);
MoveHHi ((Handle)srcA);
HLock ((Handle)srcA);
pmStateB = GetPixelsState(srcB);
LockPixels (srcB);
stateB = HGetState ((Handle)srcB);
MoveHHi ((Handle)srcB);
HLock ((Handle)srcB);
pmStateDest = GetPixelsState(dest);
LockPixels (dest);
stateDest = HGetState ((Handle)dest);
MoveHHi ((Handle)dest);
HLock ((Handle)dest);
/* save drawing state */
GetGWorld(&oldGW,&oldGD);
SetGWorld (destGW,GetGWorldDevice(destGW));
GetForeColor (&oldFore);
GetBackColor (&oldBack);
RGBForeColor ((RGBColor*)RGBBlack);
RGBBackColor ((RGBColor*)RGBWhite);
bounds = (**srcA).bounds;
/* copy entire first source image */
CopyBits((BitMap*)*srcA,(BitMap*)*dest,&bounds,&bounds,srcCopy,nil);
/* spin beachball, restoring original graphic state */
SetGWorld (oldGW,oldGD);
UpdateProgress (params,2,3);
SetGWorld (destGW,GetGWorldDevice(destGW));
/* wait for accelerators */
while (!QDDone((GrafPtr)destGW)); // Wait for accelerator.
/* copy the piece of the second source that we calculated earlier */
CopyBits((BitMap*)*srcB,(BitMap*)*dest,&r,&r,srcCopy,nil);
/* wait for accelerators */
while (!QDDone((GrafPtr)destGW)); // Wait for accelerator.
/* restore graphic state */
RGBForeColor (&oldFore);
RGBBackColor (&oldBack);
SetGWorld (oldGW,oldGD);
UpdateProgress (params,3,3);
/* restore offscreen pixmaps' state */
HSetState ((Handle)srcA,stateA);
SetPixelsState(srcA,pmStateA);
HSetState ((Handle)srcB,stateB);
SetPixelsState(srcB,pmStateB);
HSetState ((Handle)dest,stateDest);
SetPixelsState(dest,pmStateDest);
return (noErr);
}